package com.hfb.mashibing.alip8.juc.c020;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * reentrantLock 用于代替 synchronized
 * 由于m锁定this ，只有m执行完毕的时候，n才能执行
 * 这里是复习 synchronized 最原始的语义
 *
 * reentrantLock 可以完成同样的功能
 * 需要注意的是，必须要手动释放锁
 * 使用 synchronized 锁定的话，如遇异常jvm 会自动释放锁，
 * 但是lock必须手动释放，因此经常放在finally里
 *
 * 使用 reentrantLock 可以进行"尝试锁定"tryLock，
 * 这样(在规定时间内)无法锁定，代码都将继续执行
 */
public class T03_ReentrantLock3 {
    Lock lock = new ReentrantLock();

    void m () {
        try {
            lock.lock();
            for (int i = 0; i < 10; i++) {
                TimeUnit.SECONDS.sleep(1);

                System.out.println(i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }  finally {
            lock.unlock();
        }
    }

    /**
     * tryLock：不管锁定随时发成功，方法都将继续执行
     * 先可以更具tryLock 的返回值来判断是否锁定
     * 也能规定在规定时间内尝试获取锁，
     * 由于tryLock(timeInt)抛出异常，
     * 所有一定要在finally里释放锁！！！
     */
    void n() {
        boolean locked = false;
        try {
            locked = lock.tryLock(5, TimeUnit.SECONDS);

            System.out.println("n。。。" + locked);

        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            if (locked) {
                lock.unlock();
            }
        }
    }

    public static void main(String[] args) {
        T03_ReentrantLock3 lock = new T03_ReentrantLock3();
        new Thread(lock::m).start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(lock::n).start();

    }

}
